/**file uploader of java frame work
 * the file upload to temporary directory first, and then move to destination directory
 * by fuzhou huilin corp.ltd @author lms 2016.08.19
 */

package com.fzrskj.cloud.free.core.servlet;

import com.fzrskj.cloud.free.core.AppStatus;
import com.fzrskj.cloud.free.core.tool.*;
import com.fzrskj.cloud.free.core.utils.CloudContextUtils;
import com.fzrskj.cloud.free.sys.utils.AgentAccountUtils;
import com.fzrskj.cloud.free.sys.vo.AgentAccountMessageVo;
import com.winiis.component.common.utils.tool.CSysTool;
import ms.core.consts.Consts;
import ms.core.consts.SysErr;
import ms.core.support.Session;
import ms.core.support.UploadParam;
import ms.core.tool.*;
import net.sf.json.JSONObject;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class UploadServlet extends HttpServlet {
	private static final long serialVersionUID = 1000L;	
	final private String tempUrl = "/upload";
	/**
	 * Constructor of the object.
	 */
	public UploadServlet() {
		super();
	}

	/**
	 * Destruction of the servlet. <br>
	 */
	@Override
	public void destroy() {
		super.destroy(); // Just puts "destroy" string in log
		// Put your code here
	}

	/**The doGet method of the servlet. <br>
	 * This method is called when a form has its tag value method equals to get.
	 * @param request the request send by the client to the server
	 * @param response the response send by the server to the client
	 * @throws ServletException if an error occurred
	 * @throws IOException if an error occurred
	 */
	@Override
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doPost(request, response);
	}

	/**The doPost method of the servlet. <br>
	 * This method is called when a form has its tag value method equals to post.
	 * @param request the request send by the client to the server
	 * @param response the response send by the server to the client
	 * @throws ServletException if an error occurred
	 * @throws IOException if an error occurred
	 */
	@Override
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		try {

			//设置debug
			AppStatus.setDebug(Boolean.valueOf(SystemConfig.getProper("debug")));

			//代理信息设置;
			AgentAccountMessageVo messageVo = new AgentAccountMessageVo();
			if (!AgentAccountUtils.setAgentInfo(request, messageVo)) {
				response.setStatus(403);
				String ret = XmlCodeParser.formatResultTips(false, messageVo.getCode(), messageVo.getMessage());
				CResponseTool.doResponseText(response, ret);
				return;
			}

			String sid = CCookieTool.getSessionId(request);
			Session session = CSessionTool.getSessionCloud(sid);
			if (null == session) {
				CSessionTool.newSessionCloud(sid);
				session = CSessionTool.getSessionCloud(sid);
			}

			//代理设置登录
			if (messageVo.getNewSession()) {
				session = new Session();
				session.setId(messageVo.getUserAccount().getId());
				session.setUID(messageVo.getUserAccount().getUserId());
				session.setUname(messageVo.getUserAccount().getUserName());
				//set user account email
				session.setData(messageVo.getUserAccount().toJsonString());
				session.setUtype(1);
				//TODO to fill user functions
				session.setFuncs("");
				CSessionTool.setLoginSessionCloud(sid, session);
			}
			CloudContextUtils.setSession(session);

			//WEB-INF can't be vist outside to make sur of security
			String savePath = Consts.STATIC_PATH + "/upload";
			String tempPath = request.getSession().getServletContext().getRealPath("/temp");
			CSysTool.dirExists(savePath, true);
			CSysTool.dirExists(tempPath, true);

			JSONObject obj=new JSONObject();
			//1. create DiskFileItemFactory, and set cache size and temp path
			DiskFileItemFactory factory = new DiskFileItemFactory();
			factory.setSizeThreshold(102400);
			File tmpFile = new File(tempPath);
			factory.setRepository(tmpFile);
			//2. create file upload servlet and upload progress listner
			ServletFileUpload upload = new ServletFileUpload(factory);
			upload.setHeaderEncoding("UTF-8");	//file name encode
			upload.setFileSizeMax(1024*1024*100);	//file max size limited
			upload.setSizeMax(1024*1024*1000);	//file total size=(one file size) * (file count)
			upload.setProgressListener(new ProgressListener(){
				@Override
				public void update(long pBytesRead, long pContentLength, int arg2){
					System.out.println("file size:" + pContentLength + ",uploaded:" + pBytesRead);
				}
			});
			//3.is it form data?
			if(!ServletFileUpload.isMultipartContent(request)){
				response.setStatus(400);
				String ret = XmlCodeParser.formatResultTips(false, "MultipartContent Error", "is not form data");
				CResponseTool.doResponseText(response, ret);
				return;
			}
			//4.analysis file form
			List<FileItem> list = upload.parseRequest(request);

			String urlHead = this.tempUrl;

			//set user path
			//to get parameter and verify it
			String addPath = "/public";
			String upname = getParameter(list, "upname");
			if (!StrTool.isBlankStr(upname)) {
				UploadParam up = XmlUploadParser.getUploadParam(upname);
				if (up == null) {
					ResponseTool.doResponseText(response, request, 404, XmlCodeParser.formatResultTips(false, SysErr.FILE_UNKNOW_UPLOAD));
					return;
				}
				addPath = up.getSavePath();

				if (!addPath.startsWith("/public")  && CloudContextUtils.getSession().getUID() > 0) {
					String uid = String.valueOf(CloudContextUtils.getSession().getUID());
					addPath = addPath.replaceAll("\\{uid}", uid);
				}
			}
			savePath += addPath;
			urlHead += addPath;
			CSysTool.dirExists(savePath, true);

			for(FileItem item : list){
				if(item.isFormField()){
					String name = item.getFieldName();
					String value = item.getString("UTF-8");
					System.out.println(name+"="+value);
				}else{
					String filename = item.getName();
					if (CStrTool.isBlankStr(filename)) {
						continue;
					}
					
					filename = filename.substring(filename.lastIndexOf("\\")+1);
					String fileExtName = filename.substring(filename.lastIndexOf("."));
					System.out.println("the upload file suffix:"+fileExtName);
					InputStream in = item.getInputStream();
					String saveFilename = CSysTool.makeUUID("")+fileExtName;
					String file ="";
					if((System.getProperty ("os.name")).indexOf("Win")>-1 ||(System.getProperty ("os.name")).indexOf("win")>-1){
						file = savePath + "\\" + saveFilename;
					}else{
						file = savePath + "/" + saveFilename;
					}
					FileOutputStream out = new FileOutputStream(file);
					byte buffer[] = new byte[102400];
					int len = 0;
					while((len=in.read(buffer))>0){
						out.write(buffer, 0, len);
					}
					in.close();
					out.close();
					item.delete();	//delete file in temp dir 
					request.setAttribute("msg", filename+" upload success");
					response.setContentType("text/html;charset=UTF-8");
					if((System.getProperty ("os.name")).indexOf("Win")>-1 ||(System.getProperty ("os.name")).indexOf("win")>-1){
						obj.put("url", urlHead + "/" + saveFilename);
					}else{
						obj.put("url", urlHead + "/" + saveFilename);
					}
				
				}
			}
			response.getWriter().print(obj.toString());
		} catch (Exception e) {
			e.printStackTrace();
			ResponseTool.doResponseText(response, request, 400, XmlCodeParser.formatResultTips(false, "exception", e.getMessage()));
			return;
		}
	}

	/**
	 * Initialization of the servlet. <br>
	 *
	 * @throws ServletException if an error occurs
	 */
	@Override
	public void init() throws ServletException {
		// Put your code here
	}


	private String getParameter(List<FileItem> list, String key){
		String ret = null;
		try{
			for(FileItem item: list){
				if (item.getFieldName().toLowerCase().equals(key)){
					ret = item.getString("UTF-8");
					break;
				}
			}
		}catch(Exception e){

		}
		return ret;
	}
}
